
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <stdbool.h>
#include <arpa/inet.h>
#include <sys/inotify.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/epoll.h>

#include "tcpa_monitor.h"
#include "read_json.h"
#include "user_proc.h"
#include "tcpa_util.h"

tcpa_monitor_t *tcpa_monitor_create(void)
{
    tcpa_monitor_t *monitor = (tcpa_monitor_t *) malloc(sizeof(tcpa_monitor_t));
    if (monitor == NULL) {
        return NULL;
    }
    memset(monitor, 0, sizeof(tcpa_monitor_t));
    strcpy(monitor->pep_svn_info.file_path, TD_RCSTNETCFG_FILE_PATH);
    strcpy(monitor->tcpam_cfg_file_ctx.tcpa_cfg_file[TCPA_CFG].cfg_name, "tcpa_cfg");
    strcpy(monitor->tcpam_cfg_file_ctx.tcpa_cfg_file[TCPA_CFG].file_path, TCPA_CFG_FILE_DEFAULT_PATH);
    strcpy(monitor->tcpam_cfg_file_ctx.tcpa_cfg_file[WHITELIST_CFG].cfg_name, "whitelist");
    strcpy(monitor->tcpam_cfg_file_ctx.tcpa_cfg_file[WHITELIST_CFG].file_path, TCPA_WHITELIST_CFG_FILE_DEFAULT_PATH);

    return monitor;
}

void tcpa_monitor_destroy(tcpa_monitor_t *monitor)
{
    TCPAM_LOG_INFO("tcpa monitor destroy");
    if (monitor == NULL) {
        return;
    }
    free(monitor);
}

int tcpa_monitor_stop(tcpa_monitor_t* monitor)
{
    TCPAM_LOG_INFO("tcpa_monitor_stop");
    monitor->monitor_status = TCPA_MONITOR_STATUS_EXIT;
    // 清理白名单
    TCPAM_LOG_INFO("clean whitelist");
    call_clean_whitelist_sh(monitor);
    // 关闭监控线程
    TCPAM_LOG_INFO("close inotify_thread_fd");
    write(monitor->tcpam_cfg_file_ctx.exit_use_pipe[1], "stop", strlen("stop"));
    close(monitor->tcpam_cfg_file_ctx.exit_use_pipe[1]);
    // 等待监控线程退出
    pthread_join(monitor->tcpam_cfg_file_ctx.inotify_thread_fd, NULL);
    // pthread_cancel(monitor->tcpam_cfg_file_ctx.inotify_thread_fd);

    // 释放tcpa_ctrl_node 安全方式遍历，可以删除节点（停止应用程序）
    TCPAM_LOG_INFO("free tcpa_ctrl_node");
    tcpa_ctrl_t *ctrl_node = NULL, *ctrl_temp = NULL;
    list_for_each_entry_safe(ctrl_node, ctrl_temp, &monitor->tcpa_ctrl_list, node) { 
        list_del(&ctrl_node->node);
        stop_tcpa_util(ctrl_node);
        clean_tcpa_ctrl(ctrl_node);
        safe_free(ctrl_node);
    }
    // 删除iptables入口规则
    call_disable_whitelist_sh("all");
    if (monitor->net_mode == NET_MODE_NAT) {
        call_disable_nat("0.0.0.0", "all");
    }

    // 释放rule_node 安全方式遍历，可以删除节点
    TCPAM_LOG_INFO("free rule_list");
    rule_cfg_t *rule_node = NULL, *rule_temp = NULL;
    list_for_each_entry_safe(rule_node, rule_temp, &monitor->rule_list, node) { 
        list_del(&rule_node->node);
        safe_free(rule_node);
    }
    deinit_proc_file(monitor->uproc_fd_tcpamonitor);
    deinit_proc_file(monitor->uproc_fd_tcpacfg);
    deinit_proc_file(monitor->uproc_fd_whitelist);

    monitor->monitor_status = TCPA_MONITOR_STATUS_STOP;
    return 0;
}

int read_rcstnetcfg_json(tcpa_monitor_t *monitor)
{
    // 从/etc/parameters/rcstnetcfg.json中读取server_ip配置，并写入tcpa_cfg配置文件
    json_member_t whitelist_json_member[JSON_MEMBER_MAX_NUM] = {0};
    int json_member_num = jsonfile_to_keyvalue(whitelist_json_member, JSON_MEMBER_MAX_NUM, monitor->pep_svn_info.file_path);
    if (json_member_num <= 0) {
        TCPAM_LOG_ERROR("read rcstnetcfg json failed. file_path:%s", monitor->pep_svn_info.file_path);
        readjson_error_code_interpret(json_member_num);
        return -1;
    }
    
    int i = 0, find_net_route_ok = 0, find_net_nat_ok = 0;
    for (i = 0; i < json_member_num; i++) {
        if (strcmp(whitelist_json_member[i].key, NET_MODE_STR[NET_MODE_ROUTE]) == 0) {
            find_net_route_ok = 1;
            monitor->net_mode = NET_MODE_ROUTE;
            break;
        }
        if (strcmp(whitelist_json_member[i].key, NET_MODE_STR[NET_MODE_NAT]) == 0) {
            find_net_nat_ok = 1;
            monitor->net_mode = NET_MODE_NAT;
            break;
        }
    }
    if (find_net_route_ok || find_net_nat_ok) {
        int find_flag = 0, case_svn_flag = 0, case_pep_server_ip_flag = 0;
        int json_array_num = 0;
        pep_svn_info_t *pep_svn_info = &(monitor->pep_svn_info);
        int *svn_num = &(pep_svn_info->svn_num);

        TCPAM_LOG_INFO("read rcstnetcfg json. net_mode: %s", get_net_mode_str(monitor->net_mode));
        for (int j = i + 1; j < json_member_num; j++) {
            // printf("key[%d]:%s \tvalue[%d]:%s\n", j, whitelist_json_member[j].key, j, whitelist_json_member[j].value);
            if (strcmp(whitelist_json_member[j].key, "[") == 0) {
                json_array_num++;
                continue;
            }
            if (strcmp(whitelist_json_member[j].key, "]") == 0) {
                if (--json_array_num == 0) {
                    // json数组（全部svn网络）解析完毕，退出循环
                    break;
                }
                continue;
            }
            if (find_flag) {
                if (strcmp(whitelist_json_member[j].key, "svn") == 0) {
                    pep_svn_info->pep_svn[*svn_num].svn = atoi(whitelist_json_member[j].value);
                    case_svn_flag = 1;
                }
                else if (strcmp(whitelist_json_member[j].key, "ip_nic") == 0) {
                    
                    int k = j + 1, ip_nic_start_flag = 0;
                    for (; k < json_member_num; k++) {
                        // ] 结束
                        if (strcmp(whitelist_json_member[k].key, "]") == 0) {
                            break;
                        }
                        // [ 开始
                        else if (strcmp(whitelist_json_member[k].key, "[") == 0) {
                            ip_nic_start_flag = 1;
                            continue;
                        }
                        // 解析ip_nic
                        if (ip_nic_start_flag) {
                            char output_buf[2][128];
                            int output_buf_len = sizeof(output_buf);;
                            int output_num = cut_str_for_keyword(output_buf, output_buf_len, whitelist_json_member[k].key, strlen(whitelist_json_member[k].key), "/");
                            // 记录IP地址
                            strcpy(pep_svn_info->pep_svn[*svn_num].now_svn_ip, output_buf[0]);
                            // printf("now_svn_ip:%s\n", pep_svn_info->pep_svn[*svn_num].now_svn_ip);
                            // 记录掩码
                            pep_svn_info->pep_svn[*svn_num].ip_mask = atoi(output_buf[1]);
                            // 使用第一个ip_nic
                            break;
                        }
                    }
                }
                else if (strcmp(whitelist_json_member[j].key, "pep_server") == 0) {
                    int find_pep_server_flag = 0;
                    int *pep_server_num = &(pep_svn_info->pep_svn[*svn_num].pep_server_num);
                    // 解析pep_server
                    int k = j + 1;
                    for (; k < json_member_num; k++) {
                        if (strcmp(whitelist_json_member[k].key, "]") == 0) {
                            break;
                        }
                        if (find_pep_server_flag) {
                            if (strcmp(whitelist_json_member[k].key, "}") == 0) {
                                find_pep_server_flag = 0;
                                (*pep_server_num)++;
                            }
                            if (strcmp(whitelist_json_member[k].key, "g_bnn_id") == 0) {
                                pep_svn_info->pep_svn[*svn_num].pep_server_ip[*pep_server_num].g_bnn_id = atoi(whitelist_json_member[k].value);
                            }
                            if (strcmp(whitelist_json_member[k].key, "ip") == 0) {
                                strcpy(pep_svn_info->pep_svn[*svn_num].pep_server_ip[*pep_server_num].ip, whitelist_json_member[k].value);
                            }
                            continue;
                        }
                        if (strcmp(whitelist_json_member[k].key, "{") == 0) {
                            find_pep_server_flag = 1;
                        }
                    }
                    j = k;
                    case_pep_server_ip_flag = 1;
                }
                if (case_pep_server_ip_flag && case_svn_flag) {
                    case_svn_flag = 0;
                    case_pep_server_ip_flag = 0;
                    find_flag = 0;
                    (*svn_num)++;
                }
                continue;
            }
            
            if (strcmp(whitelist_json_member[j].key, "{") == 0) {
                find_flag = 1;
                continue;
            }
        }
    }
    else {
        TCPAM_LOG_WARNING("read rcstnetcfg json: net_mode(%s/%s) not found. file_path:%s", 
            NET_MODE_STR[NET_MODE_ROUTE], NET_MODE_STR[NET_MODE_NAT], monitor->pep_svn_info.file_path);
    }
    return 0;
}

int create_default_tcpa_cfg_file(char *file_path)
{
    // 创建文件
    FILE *fp = open_file_with_create_dir(file_path, "w+");
    if (fp == NULL) {
        TCPAM_LOG_ERROR("create default_tcpa_cfg file error.");
        return -1;
    }
    // 创建json文件,填充默认格式
    fprintf(fp, "[\n");
    fprintf(fp, "]\n");
    fclose(fp);
    TCPAM_LOG_INFO("create default_tcpa_cfg file success. please: sudo vi %s", file_path);

    // 创建示例文件
    char demo_file_path[CFG_FILE_PATH_LEN] = {0};
    snprintf(demo_file_path, CFG_FILE_PATH_LEN, "%s.demo", file_path);
    FILE *fp_demo = open_file_with_create_dir(demo_file_path, "w+");
    if (fp_demo == NULL) {
        TCPAM_LOG_ERROR("create tcpa_cfg demo file error.");
        return -1;
    }
    // 创建json文件,填充默认格式
    fprintf(fp_demo, "[\n");
    fprintf(fp_demo, "    {\n");
    fprintf(fp_demo, "        \"vrf_name\":\"vrf1\",\n");
    fprintf(fp_demo, "        \"enable\":false,\n");
    fprintf(fp_demo, "        \"max_connect\":%u,\n", DEFAULT_ACCELERATION_LINK_NUM);
    fprintf(fp_demo, "        \"server_ip\":\"192.168.1.1\"\n");
    fprintf(fp_demo, "    }\n");
    fprintf(fp_demo, "]\n");
    fclose(fp_demo);
    return 0;
}
int tcpa_cfg_update_from_file(tcpa_monitor_t *monitor)
{
    // read tcpa_cfg from cfg_file
    json_member_t tcpa_cfg_json_member[JSON_MEMBER_MAX_NUM] = {0};
    tcpa_cfg_file_t *tcpa_cfg_file = &monitor->tcpam_cfg_file_ctx.tcpa_cfg_file[TCPA_CFG];
    TCPAM_LOG_INFO("tcpa_cfg_file_path:%s", tcpa_cfg_file->file_path);

    if (1) {   // 打印文件内容
        FILE *fp = fopen(tcpa_cfg_file->file_path, "r");
        if (fp == NULL) {
            TCPAM_LOG_ERROR("open json file[%s] error.", tcpa_cfg_file->file_path);
            return -1;
        }
        char line[1024] = {0};
        while (fgets(line, sizeof(line), fp)) {
            printf("%s", line);
        }
        fclose(fp);
    }

    // 配置文件不存在则创建配置文件
    if (access(tcpa_cfg_file->file_path, F_OK) == -1) {
        TCPAM_LOG_INFO("tcpa_cfg_file_path:%s not exist, create default file", tcpa_cfg_file->file_path);
        if (create_default_tcpa_cfg_file(tcpa_cfg_file->file_path) < 0) {
            TCPAM_LOG_ERROR("create default tcpa_cfg file error.");
            return -1;
        }
    }

    int json_member_num = jsonfile_to_keyvalue(tcpa_cfg_json_member, JSON_MEMBER_MAX_NUM, tcpa_cfg_file->file_path);
    if (json_member_num < 0) {
        readjson_error_code_interpret(json_member_num);
        return -1;
    }
    else {
        uint32_t cfg_start_flag = 0, add_flag = 0;
        tcpa_ctrl_t *tcpa_ctrl_node = NULL;
        tcpa_cfg_t *tcpa_cfg = NULL;
        uint32_t vrf_id_list[VRF_MAX_NUM] = {0};
        monitor->tcpa_ctrl_node_num = 0;
        for (int i = 0; i < json_member_num; i++) {
            if (0) {   // 打印json内容
                if (strlen(tcpa_cfg_json_member[i].key) < 8) {
                    printf("key[%d]:%s \t\tvalue[%d]:%s\n", i, tcpa_cfg_json_member[i].key, i, tcpa_cfg_json_member[i].value);
                }
                else {
                    printf("key[%d]:%s \tvalue[%d]:%s\n", i, tcpa_cfg_json_member[i].key, i, tcpa_cfg_json_member[i].value);
                }
            }
            if (tcpa_cfg_json_member[i].key[0] == '{') {
                if ((monitor->tcpa_ctrl_node_num + 1) >= VRF_MAX_NUM) {
                    TCPAM_LOG_WARNING("tcpa_cfg_file_path:%s has more than %d vrf", tcpa_cfg_file->file_path, VRF_MAX_NUM);
                    break;
                }
                add_flag = false;
                cfg_start_flag = true;
                tcpa_ctrl_node = (tcpa_ctrl_t *)zalloc(sizeof(tcpa_ctrl_t));
                tcpa_cfg = &tcpa_ctrl_node->tcpa_cfg;
                tcpa_cfg_set_default(tcpa_cfg, monitor->net_mode);
            }
            else if (tcpa_cfg_json_member[i].key[0] == '}') {
                cfg_start_flag = false;
                monitor->tcpa_ctrl_node_num++;
                if (add_flag == true) {
                    TCPAM_LOG_INFO("add tcpa cfg from %s", tcpa_ctrl_node->vrf_name);
                    list_add_tail(&tcpa_ctrl_node->node, &monitor->tcpa_ctrl_list);
                    // print_tcpa_ctrl_list(monitor, "tcpa_ctrl_list after add");
                }
                
                // 处理需要停止或者删除的配置
                if (tcpa_ctrl_node->tcpa_action_mask & TCPA_ACTION_STOP) {
                    TCPAM_LOG_INFO("stop tcpa cfg from %s", tcpa_ctrl_node->vrf_name);
                    stop_tcpa_util(tcpa_ctrl_node);
                }
                else if (tcpa_ctrl_node->tcpa_action_mask & TCPA_ACTION_RESTART) {
                    TCPAM_LOG_INFO("restart tcpa cfg from %s", tcpa_ctrl_node->vrf_name);
                    stop_tcpa_util(tcpa_ctrl_node);
                    if (tcpa_pid_ctrl_util(tcpa_ctrl_node) < 0) {
                        TCPAM_LOG_ERROR("restart tcpa[%s] error.", tcpa_ctrl_node->vrf_name);
                    }
                    else {
                        TCPAM_LOG_INFO("restart tcpa[%s] success. pid:"PRINTF_UINT64_FORMAT"", tcpa_ctrl_node->vrf_name, tcpa_ctrl_node->tcpa_pid);
                    }
                }
                // reset tcpa_action_mask
                tcpa_ctrl_node->tcpa_action_mask = 0;
            }
            else if (cfg_start_flag) {
                if ( strcmp(tcpa_cfg_json_member[i].key, TCPA_CFG_PARAMETER_KEY[TCPA_CFG_PARAMETER_VRF_ID]) == 0 ) {
                    char cut_str[5][128] = {0};
                    int cut_num = cut_str_for_keyword(cut_str, sizeof(cut_str), tcpa_cfg_json_member[i].value, strlen(tcpa_cfg_json_member[i].value), "vrf");
                    if (cut_num < 1) {
                        TCPAM_LOG_WARNING("invalid vrfname:%s", tcpa_cfg_json_member[i].value);
                        safe_free(tcpa_ctrl_node);
                        cfg_start_flag = false;
                        continue;
                    }
                    // VRF_ID == SVN_ID
                    uint32_t vrf_id = atoi(cut_str[1]);
                    tcpa_cfg_set_server_ip(tcpa_cfg, vrf_id, &monitor->pep_svn_info);

                    // 当前读出来的vrf_id在配置链表中不存在才需要add到链表
                    if (vrf_id_is_exist(monitor, vrf_id)) {
                        // printf("vrf_id:%d has duplicate\n", vrf_id);
                        safe_free(tcpa_ctrl_node);
                        // 拿到已经在链表中的上下文,配置更新到其中
                        tcpa_ctrl_node = get_tcpa_ctrl_node_by_vrf_id(monitor, vrf_id);
                        tcpa_cfg = &tcpa_ctrl_node->tcpa_cfg;
                        add_flag = false;
                    }
                    else {
                        add_flag = true;
                    }
                    strcpy(tcpa_cfg->vrf_name, tcpa_cfg_json_member[i].value);
                    tcpa_cfg->vrf_id = vrf_id;
                    strcpy(tcpa_ctrl_node->vrf_name, tcpa_cfg_json_member[i].value);
                    tcpa_ctrl_node->vrf_id = vrf_id;
                    vrf_id_list[monitor->tcpa_ctrl_node_num] = vrf_id;
                }
                else if ( strcmp(tcpa_cfg_json_member[i].key, TCPA_CFG_PARAMETER_KEY[TCPA_CFG_PARAMETER_ENABLE]) == 0 ) {
                    if (strcmp(tcpa_cfg_json_member[i].value, "true") == 0 || strcmp(tcpa_cfg_json_member[i].value, "on") == 0) {
                        tcpa_cfg->tcpa_enable = true;
                    }
                    else {
                        tcpa_cfg->tcpa_enable = false;
                        if (tcpa_is_running(tcpa_ctrl_node)) {
                            TCPAM_LOG_INFO("vrf:%s["PRINTF_UINT64_FORMAT"] disable. need stop.", tcpa_ctrl_node->vrf_name, tcpa_ctrl_node->tcpa_pid);
                            tcpa_ctrl_node->tcpa_action_mask |= TCPA_ACTION_STOP;
                        }
                    }
                }
                else if ( strcmp(tcpa_cfg_json_member[i].key, TCPA_CFG_PARAMETER_KEY[TCPA_CFG_PARAMETER_MAX_CONNECT]) == 0 ) {
                    int new_value = atoi(tcpa_cfg_json_member[i].value);
                    if (new_value != tcpa_cfg->max_connect) {
                        if (tcpa_is_running(tcpa_ctrl_node)) {
                            TCPAM_LOG_INFO("vrf:%s["PRINTF_UINT64_FORMAT"] max_connect[%u] change to %u. need restart.", tcpa_ctrl_node->vrf_name, tcpa_ctrl_node->tcpa_pid, tcpa_cfg->max_connect, new_value);
                            tcpa_ctrl_node->tcpa_action_mask |= TCPA_ACTION_RESTART;
                        }
                        tcpa_cfg->max_connect = new_value;
                    }
                }
                else if ( strcmp(tcpa_cfg_json_member[i].key, TCPA_CFG_PARAMETER_KEY[TCPA_CFG_PARAMETER_SERVER_IP]) == 0 ) {
                    char new_value[16] = {0};
                    strncpy(new_value, tcpa_cfg_json_member[i].value, sizeof(new_value));
                    if (strcmp(new_value, tcpa_cfg->server_ip_str) != 0) {                      
                        if (tcpa_is_running(tcpa_ctrl_node)) {
                            TCPAM_LOG_INFO("vrf:%s["PRINTF_UINT64_FORMAT"] server_ip[%s] change to %s. need restart.", tcpa_ctrl_node->vrf_name, tcpa_ctrl_node->tcpa_pid, tcpa_cfg->server_ip_str, new_value);
                            tcpa_ctrl_node->tcpa_action_mask |= TCPA_ACTION_RESTART;
                        }
                        strcpy(tcpa_cfg->server_ip_str, new_value);
                    }
                }
                else if ( strcmp(tcpa_cfg_json_member[i].key, TCPA_CFG_PARAMETER_KEY[TCPA_CFG_PARAMETER_SERVER_PORT]) == 0 ) {
                    int new_value = atoi(tcpa_cfg_json_member[i].value);
                    if (new_value != tcpa_cfg->server_port) {
                        if (tcpa_is_running(tcpa_ctrl_node)) {
                            TCPAM_LOG_INFO("vrf:%s["PRINTF_UINT64_FORMAT"] server_port[%u] change to %u. need restart.", tcpa_ctrl_node->vrf_name, tcpa_ctrl_node->tcpa_pid, tcpa_cfg->server_port, new_value);
                            tcpa_ctrl_node->tcpa_action_mask |= TCPA_ACTION_RESTART;
                        }
                        tcpa_cfg->server_port = new_value;
                    }
                }
                else if ( strcmp(tcpa_cfg_json_member[i].key, TCPA_CFG_PARAMETER_KEY[TCPA_CFG_PARAMETER_LISTEN_PORT]) == 0 ) {
                    int new_value = atoi(tcpa_cfg_json_member[i].value);
                    if (new_value != tcpa_cfg->listen_port) {
                        if (tcpa_is_running(tcpa_ctrl_node)) {
                            TCPAM_LOG_INFO("vrf:%s["PRINTF_UINT64_FORMAT"] listen_port[%u] change to %u. need restart.", tcpa_ctrl_node->vrf_name, tcpa_ctrl_node->tcpa_pid, tcpa_cfg->listen_port, new_value);
                            tcpa_ctrl_node->tcpa_action_mask |= TCPA_ACTION_RESTART;
                        }
                        tcpa_cfg->listen_port = new_value;
                    }
                }
                else {
                    TCPAM_LOG_WARNING("unknown key:%s", tcpa_cfg_json_member[i].key);
                }
            }
        }

        // 处理删除的配置 vrf[1] [3] [2] => vrf[1] [2] [4] ;  need delete vrf[3]
        tcpa_ctrl_t *pNode = NULL, *pTemp = NULL;
        list_for_each_entry_safe(pNode, pTemp, &monitor->tcpa_ctrl_list, node) {
            uint32_t delete_flag = true;
            for (int j = 0; j < monitor->tcpa_ctrl_node_num; j++) {
                // printf("compare vrf_id:%d with vrf_id_list[%d]:%d\n", pNode->tcpa_cfg.vrf_id, j, vrf_id_list[j]);
                if (pNode->tcpa_cfg.vrf_id == vrf_id_list[j]) {
                    delete_flag = false;
                    break;
                }
            }
            if (delete_flag) {

                // ？是否需要清理白名单（此vrf下无加速程序运行，不再需要白名单）
                // TCPAM_LOG_INFO("del vrf:[%s] rule_list", pNode->vrf_name);
                // call_del_whitelist_vrf_sh(pNode->vrf_name);

                // 处理需要停止或者删除的加速配置
                TCPAM_LOG_INFO("delete vrf_id:%d", pNode->tcpa_cfg.vrf_id);
                list_del(&pNode->node);
                stop_tcpa_util(pNode);
                clean_tcpa_ctrl(pNode);
                safe_free(pNode);
                print_tcpa_ctrl_list(monitor, "tcpa_ctrl_list after delete.");
            }            
        }
    }
    return 0;
}

int creat_default_whitelist_file(char *file_path)
{
    // 创建文件
    FILE *fp = fopen(file_path, "w");
    if (fp == NULL) {
        TCPAM_LOG_ERROR("create json file error.");
        return -1;
    }
    // 创建json文件,填充默认格式
    fprintf(fp, "[\n");
    fprintf(fp, "]\n");
    fclose(fp);
    TCPAM_LOG_INFO("create default_whitelist config file success. please: sudo vi %s", file_path);
    // 创建软链接，供网管查询使用
    char shell_cmd[1024] = {0};
    snprintf(shell_cmd, sizeof(shell_cmd), "ln -s %s %s", TCPA_WHITELIST_CFG_FILE_DEFAULT_PATH, TCPA_WHITELIST_CFG_FILE_LINK_PATH);
    run_shell_cmd(NULL, 0, shell_cmd, 0);
    
    // 创建示例文件
    char demo_file_path[CFG_FILE_PATH_LEN] = {0};
    snprintf(demo_file_path, CFG_FILE_PATH_LEN, "%s.demo", file_path);
    FILE *fp_demo = open_file_with_create_dir(demo_file_path, "w+");
    if (fp_demo == NULL) {
        TCPAM_LOG_ERROR("create tcpa_cfg demo file error.");
        return -1;
    }
    // 创建json文件,填充默认格式
    fprintf(fp_demo, "[\n");
    fprintf(fp_demo, "    {\n");
    fprintf(fp_demo, "        \"vrf_name\":\"vrf1\",\n");
    fprintf(fp_demo, "        \"src_ip\":\"10.0.0.0/8\",\n");
    fprintf(fp_demo, "        \"src_port\":0,\n");
    fprintf(fp_demo, "        \"dst_ip\":\"192.168.0.0/16\",\n");
    fprintf(fp_demo, "        \"dst_port\":0\n");
    fprintf(fp_demo, "    }\n");
    fprintf(fp_demo, "]\n");
    fclose(fp_demo);
    return 0;
}
int whitelist_cfg_init_from_file(tcpa_monitor_t *monitor)
{
    // read whitelists cfg from cfg_file
    json_member_t whitelist_json_member[JSON_MEMBER_MAX_NUM] = {0};
    tcpa_cfg_file_t *whitelist_cfg_file = &monitor->tcpam_cfg_file_ctx.tcpa_cfg_file[WHITELIST_CFG];
    TCPAM_LOG_INFO("whitelist_cfg_file_path:%s", whitelist_cfg_file->file_path);

    // 配置文件不存在则创建配置文件
    if (access(whitelist_cfg_file->file_path, F_OK) == -1) {
        TCPAM_LOG_INFO("whitelist_cfg_file_path:%s not exist, create default file", whitelist_cfg_file->file_path);
        if (creat_default_whitelist_file(whitelist_cfg_file->file_path) < 0) {
            TCPAM_LOG_ERROR("create default whitelist_cfg file error.");
            return -1;
        }
    }

    int json_member_num = jsonfile_to_keyvalue(whitelist_json_member, JSON_MEMBER_MAX_NUM, whitelist_cfg_file->file_path);
    if (json_member_num < 0) {
        readjson_error_code_interpret(json_member_num);
        return -1;
    }
    else {
        uint32_t cfg_start_flag = 0;
        rule_cfg_t *rule_cfg = NULL; 
        // 全部清除过于暴力，且操作iptables耗时长，改为只清除不再使用的规则
        // reset_white_list_rule_list(monitor);
        whitelist_rule_set_unuse(&monitor->rule_list);
        for (int i = 0; i < json_member_num; i++) {
            // TCPAM_LOG_INFO("key[%d]:%s \tvalue[%d]:%s", i, whitelist_json_member[i].key, i, whitelist_json_member[i].value);
            if (strlen(whitelist_json_member[i].key) < 8) {
                printf("key[%d]:%s \t\tvalue[%d]:%s\n", i, whitelist_json_member[i].key, i, whitelist_json_member[i].value);
            }
            else {
                printf("key[%d]:%s \tvalue[%d]:%s\n", i, whitelist_json_member[i].key, i, whitelist_json_member[i].value);
            }
            if (whitelist_json_member[i].key[0] == '{') {
                if ((monitor->rule_node_num + 1) >= VRF_MAX_NUM) {
                    TCPAM_LOG_WARNING("whitelist_file_path:%s has more than %d vrf", whitelist_cfg_file->file_path, WHITE_LIST_RULE_MAX_NUM);
                    break;
                }
                cfg_start_flag = true;
                rule_cfg = (rule_cfg_t *)zalloc(sizeof(rule_cfg_t)); 
            }
            else if (cfg_start_flag && (whitelist_json_member[i].key[0] == '}')) {
                cfg_start_flag = false;
                // 校验该规则是否已经存在
                if (rule_cfg_is_exist(&monitor->rule_list, rule_cfg) == true) {
                    safe_free(rule_cfg);
                    continue;
                }
                else if (call_add_whitelist_rule_sh(rule_cfg) < 0) {
                    TCPAM_LOG_WARNING("add rule_cfg failed");
                    safe_free(rule_cfg);
                    continue;
                }
                rule_cfg->in_use = true;
                list_add_tail(&rule_cfg->node, &monitor->rule_list);
                monitor->rule_node_num++;
            } 
            else if (cfg_start_flag) {

                if ( strcmp(whitelist_json_member[i].key, WHITELIST_CFG_PARAMETER_KEY[WHITELIST_CFG_PARAMETER_VRF_ID]) == 0 ) {
                    char cut_str[5][128] = {0};
                    int cut_num = cut_str_for_keyword(cut_str, sizeof(cut_str), whitelist_json_member[i].value, strlen(whitelist_json_member[i].value), "vrf");
                    if (cut_num < 1) {
                        TCPAM_LOG_WARNING("invalid vrfname:%s", whitelist_json_member[i].value);
                        safe_free(rule_cfg);
                        cfg_start_flag = false;
                        continue;
                    }
                    strcpy(rule_cfg->vrf_name, whitelist_json_member[i].value);
                    rule_cfg->vrf_id = atoi(cut_str[1]);
                    if (get_svn_ip(&monitor->pep_svn_info, rule_cfg->vrf_id, rule_cfg->local_ip_str, sizeof(rule_cfg->local_ip_str)) < 0) {
                        TCPAM_LOG_WARNING("get_svn_ip failed. svn[%u] is invalid.", rule_cfg->vrf_id);
                        safe_free(rule_cfg);
                        cfg_start_flag = false;
                        continue;
                    }
                }
                else if ( strcmp(whitelist_json_member[i].key, WHITELIST_CFG_PARAMETER_KEY[WHITELIST_CFG_PARAMETER_SRC_IP]) == 0 ) {
                    strcpy(rule_cfg->src_ip_str, whitelist_json_member[i].value);
                    rule_cfg->src_ip = inet_addr(rule_cfg->src_ip_str);
                }
                else if ( strcmp(whitelist_json_member[i].key, WHITELIST_CFG_PARAMETER_KEY[WHITELIST_CFG_PARAMETER_SRC_PORT]) == 0 ) {
                    rule_cfg->src_port = atoi(whitelist_json_member[i].value);
                }
                else if ( strcmp(whitelist_json_member[i].key, WHITELIST_CFG_PARAMETER_KEY[WHITELIST_CFG_PARAMETER_DST_IP]) == 0 ) {
                    strcpy(rule_cfg->dst_ip_str, whitelist_json_member[i].value);
                    rule_cfg->dst_ip = inet_addr(rule_cfg->dst_ip_str);
                }
                else if ( strcmp(whitelist_json_member[i].key, WHITELIST_CFG_PARAMETER_KEY[WHITELIST_CFG_PARAMETER_DST_PORT]) == 0 ) {
                    rule_cfg->dst_port = atoi(whitelist_json_member[i].value);
                }
                else {
                    TCPAM_LOG_WARNING("unknown key:%s", whitelist_json_member[i].key);
                }
            }
        }

        // 将未使用的规则清理掉
        rule_cfg_t *pNode = NULL, *pTemp = NULL;
        list_for_each_entry_safe(pNode, pTemp, &monitor->rule_list, node) {
            if (pNode->in_use == false) {
                call_del_whitelist_rule_sh(pNode);
                list_del(&pNode->node);
                clean_rule_cfg(pNode);
                safe_free(pNode);
                monitor->rule_node_num--;
            }
        }
    }
    return 0;
}

void *listen_cfg_file_modify_thread_func(void *arg)
{
    tcpa_monitor_t *monitor = (tcpa_monitor_t *) arg;
    tcpam_cfg_file_ctx_t *cfg_file_ctx = &monitor->tcpam_cfg_file_ctx;
    tcpa_cfg_file_t *tcpa_cfg = &cfg_file_ctx->tcpa_cfg_file[TCPA_CFG];
    tcpa_cfg_file_t *whitelist_cfg = &cfg_file_ctx->tcpa_cfg_file[WHITELIST_CFG];

    // 初始化inotify实例
    tcpa_cfg->inotify_fd = inotify_init();
    whitelist_cfg->inotify_fd = inotify_init();
    if (tcpa_cfg->inotify_fd < 0 || whitelist_cfg->inotify_fd < 0) {
        perror("inotify_init");
        exit(EXIT_FAILURE);
    }
    // 设置inotify事件（IN_CLOSE_WRITE监听文件打开后被关闭的事件，确保一次操作配置文件只触发一次事件）
    int event_mask = IN_CLOSE_WRITE;
    int ret1 = inotify_add_watch(tcpa_cfg->inotify_fd, tcpa_cfg->file_path, event_mask);
    int ret2 = inotify_add_watch(whitelist_cfg->inotify_fd, whitelist_cfg->file_path, event_mask);
    if (ret1 < 0 || ret2 < 0) {
        perror("inotify_add_watch");
        exit(EXIT_FAILURE);
    }

    // 初始化epoll实例
    cfg_file_ctx->epoll_fd = epoll_create(CFG_FILE_TYPE_MAX_NUM);
    if (cfg_file_ctx->epoll_fd < 0) {
        perror("epoll_create");
        exit(EXIT_FAILURE);
    }
    // 监听inotify的可读事件
    struct epoll_event event1 = {0}, event2 = {0};
    event1.events = EPOLLIN;
    event1.data.fd = tcpa_cfg->inotify_fd;
    ret1 = epoll_ctl(cfg_file_ctx->epoll_fd, EPOLL_CTL_ADD, tcpa_cfg->inotify_fd, &event1);
    event2.events = EPOLLIN;
    event2.data.fd = whitelist_cfg->inotify_fd;
    ret2 = epoll_ctl(cfg_file_ctx->epoll_fd, EPOLL_CTL_ADD, whitelist_cfg->inotify_fd, &event2);
    if (ret1 < 0 || ret2 < 0) {
        perror("epoll_ctl");
        exit(EXIT_FAILURE);
    }

    // 准备退出唤醒epoll_wait的pipe
    if (pipe(cfg_file_ctx->exit_use_pipe) < 0) {
        perror("pipe");
        exit(EXIT_FAILURE);
    }
    set_nonblocking(cfg_file_ctx->exit_use_pipe[0]);
    set_nonblocking(cfg_file_ctx->exit_use_pipe[1]);
    struct epoll_event exit_event = {0};
    exit_event.events = EPOLLIN;
    exit_event.data.fd = cfg_file_ctx->exit_use_pipe[0];
    if (epoll_ctl(cfg_file_ctx->epoll_fd, EPOLL_CTL_ADD, cfg_file_ctx->exit_use_pipe[0], &exit_event) < 0) {
        perror("epoll_ctl");
        exit(EXIT_FAILURE);
    }

    struct epoll_event events[CFG_FILE_TYPE_MAX_NUM] = {0};
    while (monitor->monitor_status == TCPA_MONITOR_STATUS_START || monitor->monitor_status == TCPA_MONITOR_STATUS_RUNNING) {
        // 等待epoll事件
        // TCPAM_LOG_DEBUG("listen_cfg_file_modify_thread_func wait epoll event.");
        int nfds = epoll_wait(cfg_file_ctx->epoll_fd, events, CFG_FILE_TYPE_MAX_NUM, -1);
        if (nfds < 0) {
            if (errno == EINTR) {
                // 系统调用被中断，重新调用epoll_wait
                continue;
            }
            // perror("epoll_wait");
            TCPAM_LOG_WARNING("epoll_wait error:%s", strerror(errno));
            continue;
        }
        for (int n = 0; n < nfds; n++) {
            /* 当inotify_fd可读时，说明配置文件被修改（inotify只监听了IN_MODIFY，查看文件不会触发可读） */
            if (events[n].data.fd == tcpa_cfg->inotify_fd) {
                char buffer[1024] = {0};
                int length = read(tcpa_cfg->inotify_fd, buffer, 1024);
                // 因为只监听了IN_CLOSE_WRITE，所以这里只需要判断是否为IN_CLOSE_WRITE事件
                int i = 0;
                while (i < length) {
                    struct inotify_event *event = (struct inotify_event *) &buffer[i];
                    if (event->mask & IN_CLOSE_WRITE) {
                        TCPAM_LOG_INFO("tcpa_cfg_file_path:%s has been update", tcpa_cfg->file_path);
                        // 重新读取配置文件
                        pthread_mutex_lock(&monitor->cfg_mutex);
                        int ret = tcpa_cfg_update_from_file(monitor);
                        pthread_mutex_unlock(&monitor->cfg_mutex);
                        if (ret < 0) {
                            TCPAM_LOG_WARNING("tcpa cfg init from file failed");
                        }
                    }
                    i += sizeof(struct inotify_event) + event->len;
                }
            } 
            else if (events[n].data.fd == whitelist_cfg->inotify_fd) {
                char buffer[1024] = {0};
                int length = read(whitelist_cfg->inotify_fd, buffer, 1024);
                // 因为只监听了IN_CLOSE_WRITE，所以这里只需要判断是否为IN_CLOSE_WRITE事件
                int i = 0;
                while (i < length) {
                    struct inotify_event *event = (struct inotify_event *) &buffer[i];
                    if (event->mask & IN_CLOSE_WRITE) {
                        TCPAM_LOG_INFO("whitelist_file_path:%s has been update", whitelist_cfg->file_path);
                        // 重新读取配置文件
                        if (whitelist_cfg_init_from_file(monitor) < 0) {
                            TCPAM_LOG_WARNING("whitelist cfg init from file failed");
                        }
                    }
                    i += sizeof(struct inotify_event) + event->len;
                }
            }
            else if (events[n].data.fd == cfg_file_ctx->exit_use_pipe[0]) {
                // 退出线程
                TCPAM_LOG_INFO("listen_cfg_file_modify_thread_func read stop.");
                char buffer[1024] = {0};
                read(cfg_file_ctx->exit_use_pipe[0], buffer, 1024);
                // 移除epoll监听
                epoll_ctl(cfg_file_ctx->epoll_fd, EPOLL_CTL_DEL, tcpa_cfg->inotify_fd, NULL);
                epoll_ctl(cfg_file_ctx->epoll_fd, EPOLL_CTL_DEL, whitelist_cfg->inotify_fd, NULL);
                epoll_ctl(cfg_file_ctx->epoll_fd, EPOLL_CTL_DEL, cfg_file_ctx->exit_use_pipe[0], NULL);
                break;
            }
            else {
                TCPAM_LOG_WARNING("unknown fd:%d", events[n].data.fd);
            }
        }
    }

    // 关闭inotify和epoll
    close(tcpa_cfg->inotify_fd);
    close(whitelist_cfg->inotify_fd);
    close(cfg_file_ctx->exit_use_pipe[0]);
    close(cfg_file_ctx->epoll_fd);

    TCPAM_LOG_INFO("listen_cfg_file_modify_thread_func exit");
    // 退出线程
    return NULL;
}

// 监听配置文件的修改
int listen_cfg_file_modify(tcpa_monitor_t *monitor)
{
    // 创建一个线程，监听配置文件的修改
    pthread_create(&monitor->tcpam_cfg_file_ctx.inotify_thread_fd, NULL, listen_cfg_file_modify_thread_func, monitor);
    pthread_detach(monitor->tcpam_cfg_file_ctx.inotify_thread_fd);
    return 0;
}

// int create_tcpa_cfg_file_from_svninfo(pep_svn_info_t *pep_server_info)
// {
//     // 打开文件，如果不存在则创建
//     TCPAM_LOG_INFO("create default_tcpa_cfg file.");
//     FILE *fp = open_file_with_create_dir(TCPA_CFG_FILE_DEFAULT_PATH, "w+");
//     if (fp == NULL) {
//         TCPAM_LOG_ERROR("create default_tcpa_cfg file error.");
//         return -1;
//     }
//     // 创建json文件,填充默认格式（配置不能直接覆盖，需要考虑保留用户配置，修改tcp_server_ip）
//     fprintf(fp, "[\n");
//     for (int j = 0; j < pep_server_info->svn_num; j++) {
//         fprintf(fp, "    {\n");
//         fprintf(fp, "        \"vrf_name\":\"vrf%d\",\n", pep_server_info->pep_svn[j].svn);
//         fprintf(fp, "        \"enable\":%s,\n", (pep_server_info->pep_svn[j].svn == 0) ? "false" : "true");
//         fprintf(fp, "        \"max_connect\":%u,\n", DEFAULT_ACCELERATION_LINK_NUM);
//         char server_ip[16] = {0};
//         for (int k = 0; k < pep_server_info->pep_svn[j].pep_server_num; k++) {
//             if (pep_server_info->pep_svn[j].pep_server_ip[k].g_bnn_id == pep_server_info->now_g_bnn_id) {
//                 // 找到当前小站登录的gbnn对应的pep_server_ip
//                 strcpy(server_ip, pep_server_info->pep_svn[j].pep_server_ip[k].ip);
//                 break;
//             }
//         }
//         fprintf(fp, "        \"server_ip\":\"%s\"\n", server_ip);
//         fprintf(fp, "    %s\n", (j == (pep_server_info->svn_num - 1)) ? "}" : "},");
//     }
//     fprintf(fp, "]\n");
//     fclose(fp);
//     return 0;
// }

int update_pep_server_ip_every_svn(pep_svn_info_t *pep_server_info)
{
    // 遍历当前的svn网络
    for (int j = 0; j < pep_server_info->svn_num; j++) {
        // printf("[%d] svn:%d\n", j, pep_server_info->pep_svn[j].svn);
        // 遍历每个svn网络中的gbnn
        for (int k = 0; k < pep_server_info->pep_svn[j].pep_server_num; k++) {
            // printf("    g_bnn_id:%d, ip:%s\n", pep_server_info->pep_svn[j].pep_server_ip[k].g_bnn_id, pep_server_info->pep_svn[j].pep_server_ip[k].ip);
            // 找到当前小站登录的gbnn对应的pep_server_ip
            if (pep_server_info->pep_svn[j].pep_server_ip[k].g_bnn_id == pep_server_info->now_g_bnn_id) {
                // 找到当前小站登录的gbnn对应的pep_server_ip
                strcpy(pep_server_info->pep_svn[j].now_pep_server_ip, pep_server_info->pep_svn[j].pep_server_ip[k].ip);
                break;
            }
        }
        // 当前svn网络中没有找到当前小站登录的gbnn对应的pep_server_ip
        if (pep_server_info->pep_svn[j].now_pep_server_ip[0] == '\0') {
            TCPAM_LOG_ERROR("now_g_bnn_id[%d] can not find pep_server_ip in svn:%d", pep_server_info->now_g_bnn_id, pep_server_info->pep_svn[j].svn);
        }
    }
    return 0;
}

// 监听小站上下线
// TODO: 需要区分实现
#ifdef TD_SYSTEM
#include <papi/platform_monitor.h>
void devinfo_noticed(struct CSI_noticeCfg *pNoticeCfg, void *pArgs)
{
    tcpa_monitor_t *monitor = (tcpa_monitor_t *)pArgs;
    if (pNoticeCfg->pVal) {
        // 设备上线:0
        if (strncmp(pNoticeCfg->pVal, "0", strlen("0")) == 0) {
            TCPAM_LOG_INFO("device online");
            // 获得当前g_bnn_id
            pep_svn_info_t *pep_server_info = &(monitor->pep_svn_info);
            pep_server_info->now_g_bnn_id = run_shell_cmd(NULL, 0, GET_RCST_GBNNID_CMD, PRINT_RUN_CMD_LOG);
            // 根据当前g_bnn_id，更新pep_server_ip
            update_pep_server_ip_every_svn(pep_server_info);
            // 更新tcpa配置文件（因为小站上线之后才知道server_ip）
            tcpa_cfg_update_from_file(monitor);
            // 配置文件就绪后，再更新设备状态
            monitor->login_status = RCST_LOGIN;
        }
        else {
            // 设备下线
            TCPAM_LOG_INFO("device offline");
            // 设备下线，更新设备状态
            monitor->login_status = RCST_LOGOUT;
            // 更新g_bnn_id
            monitor->pep_svn_info.now_g_bnn_id = -1;
            // 关闭所有连接
            tcpa_ctrl_t *ctrl;
            list_for_each_entry(ctrl, &monitor->tcpa_ctrl_list, node) {
                stop_tcpa_util(ctrl);
            }
        }
    }
    return;
}
int listen_rcst_login(tcpa_monitor_t *monitor)
{
    static CSFP rc_devinfo_fd;
    int ret = cstate_open(&rc_devinfo_fd, "tcpa_accessinfo", -1);
    if (ret < 0) {
        TCPAM_LOG_ERROR("cstate_open failed:%d", ret);
        return ret;
    }
    ret = cstate_notice_listen(&rc_devinfo_fd, devinfo_noticed, monitor, "accessinfo", -1, 1, "login_status");
    if (ret < 0) {
        TCPAM_LOG_ERROR("cstate_notice_listen failed:%d", ret);
        cstate_close(&rc_devinfo_fd);
        return ret;
    }
    return 0;
}
int listen_port_mapping_modify(tcpa_monitor_t *monitor)
{
    return 0;
}
#else
int listen_rcst_login(tcpa_monitor_t *monitor)
{
    // 小站上线，获得当前g_bnn_id
    pep_svn_info_t *pep_server_info = &(monitor->pep_svn_info);
    pep_server_info->now_g_bnn_id = 0;
    // 根据当前g_bnn_id，更新pep_server_ip
    update_pep_server_ip_every_svn(pep_server_info);            
    // 更新tcpa配置文件（因为小站上线之后才知道server_ip）
    tcpa_cfg_update_from_file(monitor);
    // 配置文件就绪后，再更新设备状态
    monitor->login_status = RCST_LOGIN;
    return 0;
}
int listen_port_mapping_modify(tcpa_monitor_t *monitor)
{
    // kill -s SIGUSR1 "$pid"
    return 0;
}
#endif

int tcpa_monitor_init(tcpa_monitor_t *monitor)
{
    // 初始化list
    list_head_init(&monitor->tcpa_ctrl_list);
    list_head_init(&monitor->rule_list);

    // 初始化互斥锁
    pthread_mutex_init(&monitor->cfg_mutex, NULL);

    // 从配置文件初始化tcpa_cfg（在小站登录后再初始化）
    // if (tcpa_cfg_update_from_file(monitor) < 0) {
    //     return -1;
    // }

    // 初始化tcpa_cfg（保证配置文件存在）
    // TODO 配置文件不存在就创建，不需要填内容（小站登录后填内容）

    // 从配置文件初始化whitelist
    if (whitelist_cfg_init_from_file(monitor) < 0) {
        return -1;
    }
    // 监听配置文件的修改
    if (listen_cfg_file_modify(monitor) < 0) {
        return -1;
    }
    // 监听小站上下线（小站上线，不能修改配置文件）
    if (listen_rcst_login(monitor) < 0) {
        return -1;
    }
    // NAT模式下，监听端口映射的修改
    if (monitor->net_mode == NET_MODE_NAT) {  
        if (listen_port_mapping_modify(monitor) < 0) {
            return -1;
        }
    }

    // 初始化user_proc
    monitor->uproc_fd_tcpamonitor = init_proc_file(TCPA_MONITOR_PROC_PATH, tcpam_proc_status, monitor);
    if (monitor->uproc_fd_tcpamonitor < 0) {
        return -1;
    }
    monitor->uproc_fd_tcpacfg = init_proc_file(TCPA_MONITOR_TCPA_CFG_PATH, tcpam_proc_tcpa_cfg, monitor);
    if (monitor->uproc_fd_tcpacfg < 0) {
        return -1;
    }
    monitor->uproc_fd_whitelist = init_proc_file(TCPA_MONITOR_WHITELIST_CFG_PATH, tcpam_proc_whitelist_cfg, monitor);
    if (monitor->uproc_fd_whitelist < 0) {
        return -1;
    }

    return 0;
}